function Atom(name) {
  this.name = name;
  var split = name.split("-");
  this.element = s2e[split[0]];
  this.nucleons = parseInt(name.split("-")[1]);
  this.protons = this.element.number;
  this.neutrons = this.nucleons - this.protons;
}

var am2nc = [ [], [ 0.00,  0.00],  // 0,  1
  [-0.08, -0.08, 0.08,  0.08], // 2

  //  3
  [-0.11,  0.08,
   -0.02, -0.13,
    0.11,  0.08],

  //  4
  [-0.12,  0.07,  0.12, -0.07,
   -0.08, -0.11,  0.08,  0.11],

  //  5
   [-0.12,  0.08, 0.12, -0.08,
    -0.12, -0.16, 0.12,  0.16,
    -0.04, -0.04],

  [-0.07,  0.12,  0.15, -0.04, -0.10, -0.14,  0.10,  0.14,  0.07, -0.12, -0.15,  0.04],  //  6
  [-0.08,  0.14,  0.18, -0.06, -0.08, -0.16,  0.14,  0.14,  0.10, -0.14, -0.20,  0.02, -0.02,  0.0]  //  7
];

var ec = [ 0.4, 0.3, 0.3, -0.4,
  0.6, 0.7, 0.7, -0.6, -0.6, -0.7, -0.7, 0.6 ];

for (var i = am2nc.length; i < 16; i++) {
  am2nc.push(new NucleusCoordinates(i));
}

function NucleusCoordinates(mass) {
  var coordinates = [];
  var ar = 0.09 * Math.pow(mass, 0.333); // atomic radius
  var a = 0;
  for (var i = 0; i < mass; i++) {
    var p = i * Math.PI / (2 * mass) ;  //  polar angle
    var r = Math.abs(0.064 + ar * Math.cos(p));    //  distance from origin in 2 dimensions
    a += 0.09 * Math.PI / Math.pow(r, 0.76);             //  azimuthal angle
    coordinates.push(r * Math.sin(a));    //  x coordinate
    coordinates.push(r * Math.cos(a));    //  y coordinate
  }
  return coordinates;
}

$(document).ready(function() {
  drawNucleons($("body"));
});

function drawNucleons(root) {
  $.each(root.find("canvas.proton, canvas.neutron"), function(i, c) {
    var w = c.width;
    var h = c.height;
    if ($(c).hasClass("proton")) {
      c.getContext("2d").drawProton2(0.5 * w, 0.5 * h, 0.5 * Math.min(w, h));
    } else {
      c.getContext("2d").drawNeutron2(0.5 * w, 0.5 * h, 0.5 * Math.min(w, h));
    }
  });
}

CanvasRenderingContext2D.prototype.drawAtomicModel = function(name, x, y, scale) {
  this.drawElectronCloud(name, x, y, scale);
  this.drawNucleus(name, x, y, scale);
};

CanvasRenderingContext2D.prototype.drawNucleus = function(name, x, y, scale) {
  var n = getAtomicNumber(name);
  var m = getAtomicMass(name);
  var r = 0.14 * scale;
  var coords = am2nc[m];
  for (var i = 0; i < m; i++) {
    var xp = x + coords[i * 2] * scale;
    var yp = y + coords[i * 2 + 1] * scale;
    if (i % 2 == 0 && i < n * 2) {
      this.drawProton2(xp, yp, r);
    } else {
      this.drawNeutron2(xp, yp, r);
    }
  }
};

CanvasRenderingContext2D.prototype.drawElectronCloud = function(name, x, y, scale) {
  var gradient = this.createRadialGradient(x, y, 0.2 * scale, x, y, scale);
  gradient.addColorStop(0, "rgba(255, 192, 128, 0.9)");
  gradient.addColorStop(1, "rgba(255, 192, 128, 0.1)");
  this.fillStyle = gradient;
  this.fillCircle(x, y, scale);
}

CanvasRenderingContext2D.prototype.drawElectrons = function(name, x, y, scale) {
  this.drawElectrons2(name, x, y, scale, 0);
};

CanvasRenderingContext2D.prototype.drawElectrons2 = function(name, x, y, scale, charge) {
  var n = getAtomicNumber(name);
  var r = 0.12 * scale;
  for (var i = 0; i < n - charge; i++) {
    this.drawElectron2(x + ec[i * 2] * scale, y + ec[i * 2 + 1] * scale, r);
  }
};

CanvasRenderingContext2D.prototype.drawAtomicLegend = function(x, y, scale) {

};

CanvasRenderingContext2D.prototype.drawProton = function(x, y, r) {
  var gradient = this.createRadialGradient(x - 0.3 * r, y - 0.3 * r, 0.3 * r, x, y, 2.3 * r);
  gradient.addColorStop(0, "#9ECEFF");
  gradient.addColorStop(1, "#404040");
  this.fillStyle = gradient;
  this.fillCircle(x, y, r);
};

CanvasRenderingContext2D.prototype.drawProton2 = function(x, y, r) {
  this.drawProton(x, y, r);
  this.fillStyle = "#606060";
  this.textAlign = "center";
  this.textBaseline = "middle";
  this.font = Math.round(1.5 * r) + "px sans-serif";
  this.fillText("p", x, y - 0.1 * r, r);
  this.font = "bold " + Math.round(0.8 * r) + "px sans-serif";
  this.fillText("+", x + 0.6 * r, y - 0.6 * r, r);
};

CanvasRenderingContext2D.prototype.drawNeutron = function(x, y, r) {
  var gradient = this.createRadialGradient(x - 0.3 * r, y - 0.3 * r, 0.3 * r, x, y, 2.3 * r);
  gradient.addColorStop(0, "#E0E0E0");
  gradient.addColorStop(1, "#404040");
  this.fillStyle = gradient;
  this.fillCircle(x, y, r);
};

CanvasRenderingContext2D.prototype.drawNeutron2 = function(x, y, r) {
  this.drawNeutron(x, y, r);
  this.fillStyle = "#606060";
  this.textAlign = "center";
  this.textBaseline = "middle";
  this.font = Math.round(1.5 * r) + "px sans-serif";
  this.fillText("n", x, y - 0.1 * r, r);
};

CanvasRenderingContext2D.prototype.drawElectron = function(x, y, r) {
  var gradient = this.createRadialGradient(x - 0.3 * r, y - 0.3 * r, 0.3 * r, x, y, 1.2 * r);
  gradient.addColorStop(0, "rgba(255,144,192,0.75)");
  gradient.addColorStop(1, "rgba(160,160,160,0.75)");
  this.fillStyle = gradient;
  this.fillCircle(x, y, 0.6 * r);
};

CanvasRenderingContext2D.prototype.drawElectron2 = function(x, y, r) {
  this.drawElectron(x, y, r);
  this.fillStyle = "rgba(255,255,255,0.75)";
  this.textAlign = "center";
  this.textBaseline = "middle";
  this.font = Math.round(r) + "px sans-serif";
  this.fillText("e", x - 0.05 * r, y - 0.05 * r, r);
  this.fillText("-", x + 0.3 * r, y - 0.3 * r, r);
};

function getAtomicNumber(name) {
  switch(name.split("-")[0]) {
    case "H"  : return 1;
    case "He" : return 2;
    case "Li" : return 3;
    case "Be" : return 4;
    case "B" : return 5;

    default   : return 0;
  }
}

function getAtomicMass(name) {
  var n = name.split("-")[1];
  if (0 < n && n < 1000) {
    return n;
  } else {
    return 0;
  }
}

function getElementName(atom_name) {
  switch(atom_name.split("-")[0]) {
    case "H"  : return "Hydrogen";
    case "He" : return "Helium";
    case "Li" : return "Lithium";
    case "Be" : return "Beryllium";
    case "B" : return "Boron";

    default   : return "Nullium";
  }
}